home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 13 / CU Amiga Magazine's Super CD-ROM 13 (1997)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1997-08].iso / CUCD / Graphics / Ghostscript / src / libpng / pngpread.c < prev    next >
C/C++ Source or Header  |  1996-06-05  |  38KB  |  1,325 lines

  1.  
  2. /* pngpread.c - read a png file in push mode
  3.  
  4.    libpng 1.0 beta 3 - version 0.89
  5.    For conditions of distribution and use, see copyright notice in png.h
  6.    Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
  7.    May 25, 1996
  8.    */
  9.  
  10. #define PNG_INTERNAL
  11. #include "png.h"
  12.  
  13. #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
  14.  
  15. void
  16. png_process_data(png_structp png_ptr, png_infop info,
  17.    png_bytep buffer, png_uint_32 buffer_size)
  18. {
  19.    png_push_restore_buffer(png_ptr, buffer, buffer_size);
  20.  
  21.    while (png_ptr->buffer_size)
  22.    {
  23.       png_process_some_data(png_ptr, info);
  24.    }
  25. }
  26.  
  27. void
  28. png_process_some_data(png_structp png_ptr, png_infop info)
  29. {
  30.    switch (png_ptr->process_mode)
  31.    {
  32.       case PNG_READ_SIG_MODE:
  33.       {
  34.          png_push_read_sig(png_ptr);
  35.          break;
  36.       }
  37.       case PNG_READ_CHUNK_MODE:
  38.       {
  39.          png_push_read_chunk(png_ptr, info);
  40.          break;
  41.       }
  42.       case PNG_READ_IDAT_MODE:
  43.       {
  44.          png_push_read_IDAT(png_ptr);
  45.          break;
  46.       }
  47.       case PNG_READ_PLTE_MODE:
  48.       {
  49.          png_push_read_PLTE(png_ptr, info);
  50.          break;
  51.       }
  52. #if defined(PNG_READ_tEXt_SUPPORTED)
  53.       case PNG_READ_tEXt_MODE:
  54.       {
  55.          png_push_read_tEXt(png_ptr, info);
  56.          break;
  57.       }
  58. #endif
  59. #if defined(PNG_READ_zTXt_SUPPORTED)
  60.       case PNG_READ_zTXt_MODE:
  61.       {
  62.          png_push_read_zTXt(png_ptr, info);
  63.          break;
  64.       }
  65. #endif
  66.       case PNG_READ_END_MODE:
  67.       {
  68.          png_push_read_end(png_ptr, info);
  69.          break;
  70.       }
  71.       case PNG_SKIP_MODE:
  72.       {
  73.          png_push_skip(png_ptr);
  74.          break;
  75.       }
  76.       default:
  77.       {
  78.          png_ptr->buffer_size = 0;
  79.          break;
  80.       }
  81.    }
  82. }
  83.  
  84. void
  85. png_push_read_sig(png_structp png_ptr)
  86. {
  87.    png_byte sig[8];
  88.  
  89.    if (png_ptr->buffer_size < 8)
  90.    {
  91.       png_push_save_buffer(png_ptr);
  92.       return;
  93.    }
  94.  
  95.    png_push_fill_buffer(png_ptr, sig, 8);
  96.  
  97.    if (png_check_sig(sig, 8))
  98.    {
  99.       png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  100.    }
  101.    else
  102.    {
  103.       png_error(png_ptr, "Not a PNG file");
  104.    }
  105. }
  106.  
  107. void
  108. png_push_read_chunk(png_structp png_ptr, png_infop info)
  109. {
  110.    if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
  111.    {
  112.       png_byte chunk_start[8];
  113.  
  114.       if (png_ptr->buffer_size < 8)
  115.       {
  116.          png_push_save_buffer(png_ptr);
  117.          return;
  118.       }
  119.  
  120.       png_push_fill_buffer(png_ptr, chunk_start, 8);
  121.       png_ptr->push_length = png_get_uint_32(chunk_start);
  122.       png_memcpy(png_ptr->push_chunk_name, (png_voidp)(chunk_start + 4), 4);
  123.       png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
  124.       png_reset_crc(png_ptr);
  125.       png_calculate_crc(png_ptr, chunk_start + 4, 4);
  126.    }
  127.  
  128.    if (!png_memcmp(png_ptr->push_chunk_name, png_IHDR, 4))
  129.    {
  130.       if (png_ptr->mode != PNG_BEFORE_IHDR)
  131.          png_error(png_ptr, "Out of place IHDR");
  132.  
  133.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  134.       {
  135.          png_push_save_buffer(png_ptr);
  136.          return;
  137.       }
  138.  
  139.       png_handle_IHDR(png_ptr, info, png_ptr->push_length);
  140.       png_push_check_crc(png_ptr);
  141.       png_ptr->mode = PNG_HAVE_IHDR;
  142.    }
  143.    else if (!png_memcmp(png_ptr->push_chunk_name, png_PLTE, 4))
  144.    {
  145.       if (png_ptr->mode != PNG_HAVE_IHDR)
  146.          png_error(png_ptr, "Missing IHDR");
  147.  
  148. #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
  149.       if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
  150.          png_push_crc_skip(png_ptr, length);
  151.       else
  152. #else
  153.       {
  154.          png_push_handle_PLTE(png_ptr, png_ptr->push_length);
  155.       }
  156. #endif
  157.       png_ptr->mode = PNG_HAVE_PLTE;
  158.    }
  159.    else if (!png_memcmp(png_ptr->push_chunk_name, png_IDAT, 4))
  160.    {
  161.       png_ptr->idat_size = png_ptr->push_length;
  162.       png_ptr->mode = PNG_HAVE_IDAT;
  163.       png_ptr->process_mode = PNG_READ_IDAT_MODE;
  164.       png_push_have_info(png_ptr, info);
  165.       png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes;
  166.       png_ptr->zstream->next_out = png_ptr->row_buf;
  167.       return;
  168.    }
  169.    else if (!png_memcmp(png_ptr->push_chunk_name, png_IEND, 4))
  170.    {
  171.       png_error(png_ptr, "No image in file");
  172.    }
  173. #if defined(PNG_READ_gAMA_SUPPORTED)
  174.    else if (!png_memcmp(png_ptr->push_chunk_name, png_gAMA, 4))
  175.    {
  176.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  177.       {
  178.          png_push_save_buffer(png_ptr);
  179.          return;
  180.       }
  181.  
  182.       if (png_ptr->mode != PNG_HAVE_IHDR)
  183.          png_error(png_ptr, "Out of place gAMA");
  184.  
  185.       png_handle_gAMA(png_ptr, info, png_ptr->push_length);
  186.       png_push_check_crc(png_ptr);
  187.    }
  188. #endif
  189. #if defined(PNG_READ_sBIT_SUPPORTED)
  190.    else if (!png_memcmp(png_ptr->push_chunk_name, png_sBIT, 4))
  191.    {
  192.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  193.       {
  194.          png_push_save_buffer(png_ptr);
  195.          return;
  196.       }
  197.  
  198.       if (png_ptr->mode != PNG_HAVE_IHDR)
  199.          png_error(png_ptr, "Out of place sBIT");
  200.  
  201.       png_handle_sBIT(png_ptr, info, png_ptr->push_length);
  202.       png_push_check_crc(png_ptr);
  203.    }
  204. #endif
  205. #if defined(PNG_READ_cHRM_SUPPORTED)
  206.    else if (!png_memcmp(png_ptr->push_chunk_name, png_cHRM, 4))
  207.    {
  208.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  209.       {
  210.          png_push_save_buffer(png_ptr);
  211.          return;
  212.       }
  213.  
  214.       if (png_ptr->mode != PNG_HAVE_IHDR)
  215.          png_error(png_ptr, "Out of place cHRM");
  216.  
  217.       png_handle_cHRM(png_ptr, info, png_ptr->push_length);
  218.       png_push_check_crc(png_ptr);
  219.    }
  220. #endif
  221. #if defined(PNG_READ_tRNS_SUPPORTED)
  222.    else if (!png_memcmp(png_ptr->push_chunk_name, png_tRNS, 4))
  223.    {
  224.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  225.       {
  226.          png_push_save_buffer(png_ptr);
  227.          return;
  228.       }
  229.       if (png_ptr->mode != PNG_HAVE_IHDR &&
  230.          png_ptr->mode != PNG_HAVE_PLTE)
  231.          png_error(png_ptr, "Out of place tRNS");
  232.  
  233.       png_handle_tRNS(png_ptr, info, png_ptr->push_length);
  234.       png_push_check_crc(png_ptr);
  235.    }
  236. #endif
  237. #if defined(PNG_READ_bKGD_SUPPORTED)
  238.    else if (!png_memcmp(png_ptr->push_chunk_name, png_bKGD, 4))
  239.    {
  240.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  241.       {
  242.          png_push_save_buffer(png_ptr);
  243.          return;
  244.       }
  245.  
  246.       if (png_ptr->mode != PNG_HAVE_IHDR &&
  247.          png_ptr->mode != PNG_HAVE_PLTE)
  248.          png_error(png_ptr, "Out of place bKGD");
  249.  
  250.       png_handle_bKGD(png_ptr, info, png_ptr->push_length);
  251.       png_push_check_crc(png_ptr);
  252.    }
  253. #endif
  254. #if defined(PNG_READ_hIST_SUPPORTED)
  255.    else if (!png_memcmp(png_ptr->push_chunk_name, png_hIST, 4))
  256.    {
  257.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  258.       {
  259.          png_push_save_buffer(png_ptr);
  260.          return;
  261.       }
  262.  
  263.       if (png_ptr->mode != PNG_HAVE_PLTE)
  264.          png_error(png_ptr, "Out of place hIST");
  265.  
  266.       png_handle_hIST(png_ptr, info, png_ptr->push_length);
  267.       png_push_check_crc(png_ptr);
  268.    }
  269. #endif
  270. #if defined(PNG_READ_pHYs_SUPPORTED)
  271.    else if (!png_memcmp(png_ptr->push_chunk_name, png_pHYs, 4))
  272.    {
  273.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  274.       {
  275.          png_push_save_buffer(png_ptr);
  276.          return;
  277.       }
  278.  
  279.       if (png_ptr->mode != PNG_HAVE_IHDR &&
  280.          png_ptr->mode != PNG_HAVE_PLTE)
  281.          png_error(png_ptr, "Out of place pHYs");
  282.  
  283.       png_handle_pHYs(png_ptr, info, png_ptr->push_length);
  284.       png_push_check_crc(png_ptr);
  285.    }
  286. #endif
  287. #if defined(PNG_READ_oFFs_SUPPORTED)
  288.    else if (!png_memcmp(png_ptr->push_chunk_name, png_oFFs, 4))
  289.    {
  290.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  291.       {
  292.          png_push_save_buffer(png_ptr);
  293.          return;
  294.       }
  295.  
  296.       if (png_ptr->mode != PNG_HAVE_IHDR &&
  297.          png_ptr->mode != PNG_HAVE_PLTE)
  298.          png_error(png_ptr, "Out of place oFFs");
  299.  
  300.       png_handle_oFFs(png_ptr, info, png_ptr->push_length);
  301.       png_push_check_crc(png_ptr);
  302.    }
  303. #endif
  304. #if defined(PNG_READ_tIME_SUPPORTED)
  305.    else if (!png_memcmp(png_ptr->push_chunk_name, png_tIME, 4))
  306.    {
  307.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  308.       {
  309.          png_push_save_buffer(png_ptr);
  310.          return;
  311.       }
  312.  
  313.       if (png_ptr->mode == PNG_BEFORE_IHDR ||
  314.          png_ptr->mode == PNG_AFTER_IEND)
  315.          png_error(png_ptr, "Out of place tIME");
  316.  
  317.       png_handle_tIME(png_ptr, info, png_ptr->push_length);
  318.       png_push_check_crc(png_ptr);
  319.    }
  320. #endif
  321. #if defined(PNG_READ_tEXt_SUPPORTED)
  322.    else if (!png_memcmp(png_ptr->push_chunk_name, png_tEXt, 4))
  323.    {
  324.       if (png_ptr->mode == PNG_BEFORE_IHDR ||
  325.          png_ptr->mode == PNG_AFTER_IEND)
  326.          png_error(png_ptr, "Out of place tEXt");
  327.  
  328.       png_push_handle_tEXt(png_ptr, png_ptr->push_length);
  329.    }
  330. #endif
  331. #if defined(PNG_READ_zTXt_SUPPORTED)
  332.    else if (!png_memcmp(png_ptr->push_chunk_name, png_zTXt, 4))
  333.    {
  334.       if (png_ptr->mode == PNG_BEFORE_IHDR ||
  335.          png_ptr->mode == PNG_AFTER_IEND)
  336.          png_error(png_ptr, "Out of place zTXt");
  337.  
  338.       png_push_handle_zTXt(png_ptr, png_ptr->push_length);
  339.    }
  340. #endif
  341.    else
  342.    {
  343.       if (png_ptr->push_chunk_name[0] <41 || png_ptr->push_chunk_name[0]> 122 ||
  344.           (png_ptr->push_chunk_name[0]>90 && png_ptr->push_chunk_name[0]< 97) ||
  345.           png_ptr->push_chunk_name[1] <41 || png_ptr->push_chunk_name[1]> 122 ||
  346.           (png_ptr->push_chunk_name[1]>90 && png_ptr->push_chunk_name[1]< 97) ||
  347.           png_ptr->push_chunk_name[2] <41 || png_ptr->push_chunk_name[2]> 122 ||
  348.           (png_ptr->push_chunk_name[2]>90 && png_ptr->push_chunk_name[2]< 97) ||
  349.           png_ptr->push_chunk_name[3] <41 || png_ptr->push_chunk_name[3]> 122 ||
  350.           (png_ptr->push_chunk_name[3]>90 && png_ptr->push_chunk_name[3]< 97))
  351.       {
  352.          char msg[200];
  353.  
  354.          sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
  355.             png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
  356.             png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
  357.          png_error(png_ptr, msg);
  358.       }
  359.  
  360.       if ((png_ptr->push_chunk_name[0] & 0x20) == 0)
  361.       {
  362.          char msg[200];
  363.  
  364.          sprintf(msg, "Unknown critical chunk %c%c%c%c",
  365.             png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
  366.             png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
  367.          png_error(png_ptr, msg);
  368.       }
  369.  
  370.       png_push_crc_skip(png_ptr, png_ptr->push_length);
  371.    }
  372.    png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
  373. }
  374.  
  375. void
  376. png_push_check_crc(png_structp png_ptr)
  377. {
  378.    png_byte crc_buf[4];
  379.    png_uint_32 crc;
  380.  
  381.    png_push_fill_buffer(png_ptr, crc_buf, 4);
  382.    crc = png_get_uint_32(crc_buf);
  383.    if (((crc ^ 0xffffffffL) & 0xffffffffL) !=
  384.       (png_ptr->crc & 0xffffffffL))
  385.       png_error(png_ptr, "Bad CRC value");
  386. }
  387.  
  388. void
  389. png_push_crc_skip(png_structp png_ptr, png_uint_32 length)
  390. {
  391.    png_ptr->process_mode = PNG_SKIP_MODE;
  392.    png_ptr->skip_length = length;
  393. }
  394.  
  395. void
  396. png_push_skip(png_structp png_ptr)
  397. {
  398.    if (png_ptr->skip_length && png_ptr->save_buffer_size)
  399.    {
  400.       png_uint_32 save_size;
  401.  
  402.       if (png_ptr->skip_length < png_ptr->save_buffer_size)
  403.          save_size = png_ptr->skip_length;
  404.       else
  405.          save_size = png_ptr->save_buffer_size;
  406.  
  407.       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
  408.  
  409.       png_ptr->skip_length -= save_size;
  410.       png_ptr->buffer_size -= save_size;
  411.       png_ptr->save_buffer_size -= save_size;
  412.       png_ptr->save_buffer_ptr += (png_size_t)save_size;
  413.    }
  414.    if (png_ptr->skip_length && png_ptr->current_buffer_size)
  415.    {
  416.       png_uint_32 save_size;
  417.  
  418.       if (png_ptr->skip_length < png_ptr->current_buffer_size)
  419.          save_size = png_ptr->skip_length;
  420.       else
  421.          save_size = png_ptr->current_buffer_size;
  422.  
  423.       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
  424.  
  425.       png_ptr->skip_length -= save_size;
  426.       png_ptr->buffer_size -= save_size;
  427.       png_ptr->current_buffer_size -= save_size;
  428.       png_ptr->current_buffer_ptr += (png_size_t)save_size;
  429.    }
  430.    if (!png_ptr->skip_length)
  431.    {
  432.       if (png_ptr->buffer_size < 4)
  433.       {
  434.          png_push_save_buffer(png_ptr);
  435.          return;
  436.       }
  437.       png_push_check_crc(png_ptr);
  438.       png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  439.    }
  440. }
  441.  
  442. void
  443. png_push_fill_buffer(png_structp png_ptr, png_bytep buffer,
  444.    png_uint_32 length)
  445. {
  446.    png_bytep ptr;
  447.  
  448.    ptr = buffer;
  449.    if (png_ptr->save_buffer_size)
  450.    {
  451.       png_uint_32 save_size;
  452.  
  453.       if (length < png_ptr->save_buffer_size)
  454.          save_size = length;
  455.       else
  456.          save_size = png_ptr->save_buffer_size;
  457.  
  458.       png_memcpy(ptr, png_ptr->save_buffer_ptr, (png_size_t)save_size);
  459.       length -= save_size;
  460.       ptr += (png_size_t)save_size;
  461.       png_ptr->buffer_size -= save_size;
  462.       png_ptr->save_buffer_size -= save_size;
  463.       png_ptr->save_buffer_ptr += (png_size_t)save_size;
  464.    }
  465.    if (length && png_ptr->current_buffer_size)
  466.    {
  467.       png_uint_32 save_size;
  468.  
  469.       if (length < png_ptr->current_buffer_size)
  470.          save_size = length;
  471.       else
  472.          save_size = png_ptr->current_buffer_size;
  473.  
  474.       png_memcpy(ptr, png_ptr->current_buffer_ptr, (png_size_t)save_size);
  475.       png_ptr->buffer_size -= save_size;
  476.       png_ptr->current_buffer_size -= save_size;
  477.       png_ptr->current_buffer_ptr += (png_size_t)save_size;
  478.    }
  479. }
  480.  
  481. void
  482. png_push_save_buffer(png_structp png_ptr)
  483. {
  484.    if (png_ptr->save_buffer_size)
  485.    {
  486.       if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
  487.       {
  488.          int i;
  489.          png_bytep sp;
  490.          png_bytep dp;
  491.  
  492.          for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
  493.             i < png_ptr->save_buffer_size;
  494.             i++, sp++, dp++)
  495.          {
  496.             *dp = *sp;
  497.          }
  498.       }
  499.    }
  500.    if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
  501.       png_ptr->save_buffer_max)
  502.    {
  503.       int new_max;
  504.       png_bytep old_buffer;
  505.  
  506.       new_max = (int)(png_ptr->save_buffer_size +
  507.          png_ptr->current_buffer_size + 256);
  508.       old_buffer = png_ptr->save_buffer;
  509.       png_ptr->save_buffer = (png_bytep)
  510.          png_large_malloc(png_ptr, new_max);
  511.       png_memcpy(png_ptr->save_buffer, old_buffer,
  512.          (png_size_t)png_ptr->save_buffer_size);
  513.       png_large_free(png_ptr, old_buffer);
  514.         png_ptr->save_buffer_max = new_max;
  515.    }
  516.    if (png_ptr->current_buffer_size)
  517.    {
  518.       png_memcpy(png_ptr->save_buffer +
  519.          (png_size_t)png_ptr->save_buffer_size,
  520.          png_ptr->current_buffer_ptr,
  521.          (png_size_t)png_ptr->current_buffer_size);
  522.       png_ptr->save_buffer_size += png_ptr->current_buffer_size;
  523.       png_ptr->current_buffer_size = 0;
  524.    }
  525.    png_ptr->save_buffer_ptr = png_ptr->save_buffer;
  526.    png_ptr->buffer_size = 0;
  527. }
  528.  
  529. void
  530. png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
  531.    png_uint_32 buffer_length)
  532. {
  533.    png_ptr->current_buffer = buffer;
  534.    png_ptr->current_buffer_size = buffer_length;
  535.    png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
  536.    png_ptr->current_buffer_ptr = png_ptr->current_buffer;
  537. }
  538.  
  539. void
  540. png_push_read_IDAT(png_structp png_ptr)
  541. {
  542.    if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
  543.    {
  544.       png_byte chunk_start[8];
  545.  
  546.       if (png_ptr->buffer_size < 8)
  547.       {
  548.          png_push_save_buffer(png_ptr);
  549.          return;
  550.       }
  551.  
  552.       png_push_fill_buffer(png_ptr, chunk_start, 8);
  553.       png_ptr->push_length = png_get_uint_32(chunk_start);
  554.       png_memcpy(png_ptr->push_chunk_name,
  555.          (png_voidp)(chunk_start + 4), 4);
  556.       png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
  557.       png_reset_crc(png_ptr);
  558.       png_calculate_crc(png_ptr, chunk_start + 4, 4);
  559.       if (png_memcmp(png_ptr->push_chunk_name, png_IDAT, 4))
  560.       {
  561.          png_ptr->process_mode = PNG_READ_END_MODE;
  562.          if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
  563.             png_error(png_ptr, "Not enough compressed data");
  564.          return;
  565.       }
  566.  
  567.       png_ptr->idat_size = png_ptr->push_length;
  568.    }
  569.    if (png_ptr->idat_size && png_ptr->save_buffer_size)
  570.    {
  571.       png_uint_32 save_size;
  572.  
  573.       if (png_ptr->idat_size < png_ptr->save_buffer_size)
  574.          save_size = png_ptr->idat_size;
  575.       else
  576.          save_size = png_ptr->save_buffer_size;
  577.  
  578.       png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
  579.       png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
  580.  
  581.       png_ptr->idat_size -= save_size;
  582.       png_ptr->buffer_size -= save_size;
  583.       png_ptr->save_buffer_size -= save_size;
  584.       png_ptr->save_buffer_ptr += (png_size_t)save_size;
  585.    }
  586.    if (png_ptr->idat_size && png_ptr->current_buffer_size)
  587.    {
  588.       png_uint_32 save_size;
  589.  
  590.       if (png_ptr->idat_size < png_ptr->current_buffer_size)
  591.          save_size = png_ptr->idat_size;
  592.       else
  593.          save_size = png_ptr->current_buffer_size;
  594.  
  595.       png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
  596.       png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
  597.  
  598.       png_ptr->idat_size -= save_size;
  599.       png_ptr->buffer_size -= save_size;
  600.       png_ptr->current_buffer_size -= save_size;
  601.       png_ptr->current_buffer_ptr += (png_size_t)save_size;
  602.    }
  603.    if (!png_ptr->idat_size)
  604.    {
  605.       if (png_ptr->buffer_size < 4)
  606.       {
  607.          png_push_save_buffer(png_ptr);
  608.          return;
  609.       }
  610.  
  611.       png_push_check_crc(png_ptr);
  612.       png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
  613.    }
  614. }
  615.  
  616. void
  617. png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
  618.    png_uint_32 buffer_length)
  619. {
  620.    int ret;
  621.  
  622.    if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
  623.       png_error(png_ptr, "Extra compression data");
  624.  
  625.    png_ptr->zstream->next_in = buffer;
  626.    png_ptr->zstream->avail_in = (uInt)buffer_length;
  627.    do
  628.    {
  629.       ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
  630.       if (ret == Z_STREAM_END)
  631.       {
  632.          if (png_ptr->zstream->avail_in)
  633.             png_error(png_ptr, "Extra compressed data");
  634.          if (!png_ptr->zstream->avail_out)
  635.          {
  636.             png_push_process_row(png_ptr);
  637.          }
  638.          png_ptr->mode = PNG_AT_LAST_IDAT;
  639.          png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
  640.          break;
  641.       }
  642.       if (ret != Z_OK)
  643.          png_error(png_ptr, "Decompression Error");
  644.       if (!(png_ptr->zstream->avail_out))
  645.       {
  646.          png_push_process_row(png_ptr);
  647.          png_ptr->zstream->avail_out = (uInt)png_ptr->irowbytes;
  648.          png_ptr->zstream->next_out = png_ptr->row_buf;
  649.       }
  650.  
  651.    } while (png_ptr->zstream->avail_in);
  652. }
  653.  
  654. void
  655. png_push_process_row(png_structp png_ptr)
  656. {
  657.    png_ptr->row_info.color_type = png_ptr->color_type;
  658.    png_ptr->row_info.width = png_ptr->iwidth;
  659.    png_ptr->row_info.channels = png_ptr->channels;
  660.    png_ptr->row_info.bit_depth = png_ptr->bit_depth;
  661.    png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
  662.    png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
  663.       (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
  664.  
  665.    png_read_filter_row(png_ptr, &(png_ptr->row_info),
  666.       png_ptr->row_buf + 1, png_ptr->prev_row + 1,
  667.       (int)(png_ptr->row_buf[0]));
  668.  
  669.    png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
  670.  
  671.    if (png_ptr->transformations)
  672.       png_do_read_transformations(png_ptr);
  673.  
  674. #if defined(PNG_READ_INTERLACING_SUPPORTED)
  675.    /* blow up interlaced rows to full size */
  676.    if (png_ptr->interlaced &&
  677.       (png_ptr->transformations & PNG_INTERLACE))
  678.    {
  679.       if (png_ptr->pass < 6)
  680.          png_do_read_interlace(&(png_ptr->row_info),
  681.             png_ptr->row_buf + 1, png_ptr->pass);
  682.  
  683.       switch (png_ptr->pass)
  684.       {
  685.          case 0:
  686.          {
  687.             int i;
  688.             for (i = 0; i < 8 && png_ptr->pass == 0; i++)
  689.             {
  690.                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  691.                png_read_push_finish_row(png_ptr);
  692.             }
  693.             break;
  694.          }
  695.          case 1:
  696.          {
  697.             int i;
  698.             for (i = 0; i < 8 && png_ptr->pass == 1; i++)
  699.             {
  700.                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  701.                png_read_push_finish_row(png_ptr);
  702.             }
  703.             if (png_ptr->pass == 2)
  704.             {
  705.                for (i = 0; i < 4 && png_ptr->pass == 2; i++)
  706.                {
  707.                   png_push_have_row(png_ptr, NULL);
  708.                   png_read_push_finish_row(png_ptr);
  709.                }
  710.             }
  711.             break;
  712.          }
  713.          case 2:
  714.          {
  715.             int i;
  716.             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
  717.             {
  718.                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  719.                png_read_push_finish_row(png_ptr);
  720.             }
  721.             for (i = 0; i < 4 && png_ptr->pass == 2; i++)
  722.             {
  723.                png_push_have_row(png_ptr, NULL);
  724.                png_read_push_finish_row(png_ptr);
  725.             }
  726.             break;
  727.          }
  728.          case 3:
  729.          {
  730.             int i;
  731.             for (i = 0; i < 4 && png_ptr->pass == 3; i++)
  732.             {
  733.                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  734.                png_read_push_finish_row(png_ptr);
  735.             }
  736.             if (png_ptr->pass == 4)
  737.             {
  738.                for (i = 0; i < 2 && png_ptr->pass == 4; i++)
  739.                {
  740.                   png_push_have_row(png_ptr, NULL);
  741.                   png_read_push_finish_row(png_ptr);
  742.                }
  743.             }
  744.             break;
  745.          }
  746.          case 4:
  747.          {
  748.             int i;
  749.             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
  750.             {
  751.                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  752.                png_read_push_finish_row(png_ptr);
  753.             }
  754.             for (i = 0; i < 2 && png_ptr->pass == 4; i++)
  755.             {
  756.                png_push_have_row(png_ptr, NULL);
  757.                png_read_push_finish_row(png_ptr);
  758.             }
  759.             break;
  760.          }
  761.          case 5:
  762.          {
  763.             int i;
  764.             for (i = 0; i < 2 && png_ptr->pass == 5; i++)
  765.             {
  766.                png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  767.                png_read_push_finish_row(png_ptr);
  768.             }
  769.             if (png_ptr->pass == 6)
  770.             {
  771.                png_push_have_row(png_ptr, NULL);
  772.                png_read_push_finish_row(png_ptr);
  773.             }
  774.             break;
  775.          }
  776.          case 6:
  777.          {
  778.             png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  779.             png_read_push_finish_row(png_ptr);
  780.             if (png_ptr->pass != 6)
  781.                break;
  782.             png_push_have_row(png_ptr, NULL);
  783.             png_read_push_finish_row(png_ptr);
  784.          }
  785.       }
  786.    }
  787.    else
  788. #endif
  789.    {
  790.       png_push_have_row(png_ptr, png_ptr->row_buf + 1);
  791.       png_read_push_finish_row(png_ptr);
  792.    }
  793. }
  794.  
  795. void
  796. png_read_push_finish_row(png_structp png_ptr)
  797. {
  798.    png_ptr->row_number++;
  799.    if (png_ptr->row_number < png_ptr->num_rows)
  800.       return;
  801.  
  802.    if (png_ptr->interlaced)
  803.    {
  804.       png_ptr->row_number = 0;
  805.       png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
  806.       do
  807.       {
  808.          png_ptr->pass++;
  809.          if (png_ptr->pass >= 7)
  810.             break;
  811.          png_ptr->iwidth = (png_ptr->width +
  812.             png_pass_inc[png_ptr->pass] - 1 -
  813.             png_pass_start[png_ptr->pass]) /
  814.             png_pass_inc[png_ptr->pass];
  815.          png_ptr->irowbytes = ((png_ptr->iwidth *
  816.             png_ptr->pixel_depth + 7) >> 3) + 1;
  817.          if (!(png_ptr->transformations & PNG_INTERLACE))
  818.          {
  819.             png_ptr->num_rows = (png_ptr->height +
  820.                png_pass_yinc[png_ptr->pass] - 1 -
  821.                png_pass_ystart[png_ptr->pass]) /
  822.                png_pass_yinc[png_ptr->pass];
  823.             if (!(png_ptr->num_rows))
  824.                continue;
  825.          }
  826.          if (png_ptr->transformations & PNG_INTERLACE)
  827.             break;
  828.       } while (png_ptr->iwidth == 0);
  829.    }
  830. }
  831.  
  832.  
  833. void
  834. png_push_handle_PLTE(png_structp png_ptr, png_uint_32 length)
  835. {
  836.    if (length % 3)
  837.       png_error(png_ptr, "Invalid palette chunk");
  838.  
  839.    png_ptr->num_palette = (png_uint_16)(length / 3);
  840.    png_ptr->cur_palette = 0;
  841.    png_ptr->palette = (png_colorp)png_large_malloc(png_ptr,
  842.       png_ptr->num_palette * sizeof (png_color));
  843.    png_ptr->process_mode = PNG_READ_PLTE_MODE;
  844. }
  845.  
  846. void
  847. png_push_read_PLTE(png_structp png_ptr, png_infop info)
  848. {
  849.    while (png_ptr->cur_palette < png_ptr->num_palette &&
  850.       png_ptr->buffer_size >= 3)
  851.    {
  852.       png_byte buf[3];
  853.       png_push_fill_buffer(png_ptr, buf, 3);
  854.       png_calculate_crc(png_ptr, buf, 3);
  855.  
  856.       /* don't depend upon png_color being any order */
  857.       png_ptr->palette[png_ptr->cur_palette].red = buf[0];
  858.       png_ptr->palette[png_ptr->cur_palette].green = buf[1];
  859.       png_ptr->palette[png_ptr->cur_palette].blue = buf[2];
  860.       png_ptr->cur_palette++;
  861.    }
  862.    if (png_ptr->cur_palette == png_ptr->num_palette &&
  863.       png_ptr->buffer_size >= 4)
  864.    {
  865.       png_push_check_crc(png_ptr);
  866.       png_read_PLTE(png_ptr, info, png_ptr->palette, png_ptr->num_palette);
  867.       png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  868.    }
  869.    else
  870.    {
  871.       png_push_save_buffer(png_ptr);
  872.    }
  873. }
  874.  
  875. #if defined(PNG_READ_tEXt_SUPPORTED)
  876. void
  877. png_push_handle_tEXt(png_structp png_ptr, png_uint_32 length)
  878. {
  879.    png_ptr->current_text = (png_charp)png_large_malloc(png_ptr, length + 1);
  880.    png_ptr->current_text[(png_size_t)length] = '\0';
  881.    png_ptr->current_text_ptr = png_ptr->current_text;
  882.    png_ptr->current_text_size = length;
  883.    png_ptr->current_text_left = length;
  884.    png_ptr->process_mode = PNG_READ_tEXt_MODE;
  885. }
  886.  
  887. void
  888. png_push_read_tEXt(png_structp png_ptr, png_infop info)
  889. {
  890.    if (png_ptr->buffer_size && png_ptr->current_text_left)
  891.    {
  892.       png_uint_32 text_size;
  893.  
  894.       if (png_ptr->buffer_size < png_ptr->current_text_left)
  895.          text_size = png_ptr->buffer_size;
  896.       else
  897.          text_size = png_ptr->current_text_left;
  898.       png_push_fill_buffer(png_ptr, (png_bytep)png_ptr->current_text_ptr,
  899.          text_size);
  900.       png_calculate_crc(png_ptr, (png_bytep)png_ptr->current_text_ptr,
  901.          text_size);
  902.       png_ptr->current_text_left -= text_size;
  903.       png_ptr->current_text_ptr += (png_size_t)text_size;
  904.    }
  905.    if (!(png_ptr->current_text_left))
  906.    {
  907.       png_charp text;
  908.       png_charp key;
  909.  
  910.       if (png_ptr->buffer_size < 4)
  911.       {
  912.          png_push_save_buffer(png_ptr);
  913.          return;
  914.       }
  915.  
  916.       png_push_check_crc(png_ptr);
  917.  
  918.       key = png_ptr->current_text;
  919.       png_ptr->current_text = 0;
  920.  
  921.       for (text = key; *text; text++)
  922.          /* empty loop */ ;
  923.  
  924.       if (text != key + (png_size_t)png_ptr->current_text_size)
  925.          text++;
  926.  
  927.       png_read_tEXt(png_ptr, info, key, text,
  928.          png_ptr->current_text_size - (text - key));
  929.  
  930.       if (png_ptr->mode == PNG_AT_LAST_IDAT ||
  931.          png_ptr->mode == PNG_AFTER_IDAT)
  932.       {
  933.          png_ptr->process_mode = PNG_READ_END_MODE;
  934.       }
  935.       else
  936.       {
  937.          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  938.       }
  939.    }
  940. }
  941. #endif
  942.  
  943. #if defined(PNG_READ_zTXt_SUPPORTED)
  944. void
  945. png_push_handle_zTXt(png_structp png_ptr,
  946.    png_uint_32 length)
  947. {
  948.    png_ptr->current_text = (png_charp)png_large_malloc(png_ptr, length + 1);
  949.    png_ptr->current_text[(png_size_t)length] = '\0';
  950.    png_ptr->current_text_ptr = png_ptr->current_text;
  951.    png_ptr->current_text_size = length;
  952.    png_ptr->current_text_left = length;
  953.    png_ptr->process_mode = PNG_READ_zTXt_MODE;
  954. }
  955.  
  956. void
  957. png_push_read_zTXt(png_structp png_ptr, png_infop info)
  958. {
  959.    if (png_ptr->buffer_size && png_ptr->current_text_left)
  960.    {
  961.       png_uint_32 text_size;
  962.  
  963.       if (png_ptr->buffer_size < png_ptr->current_text_left)
  964.          text_size = png_ptr->buffer_size;
  965.       else
  966.          text_size = png_ptr->current_text_left;
  967.       png_push_fill_buffer(png_ptr, (png_bytep)png_ptr->current_text_ptr,
  968.          text_size);
  969.       png_calculate_crc(png_ptr, (png_bytep)png_ptr->current_text_ptr,
  970.          text_size);
  971.       png_ptr->current_text_left -= text_size;
  972.       png_ptr->current_text_ptr += (png_size_t)text_size;
  973.    }
  974.    if (!(png_ptr->current_text_left))
  975.    {
  976.       png_charp text;
  977.       png_charp key;
  978.       int ret;
  979.       png_uint_32 text_size, key_size;
  980.  
  981.       if (png_ptr->buffer_size < 4)
  982.       {
  983.          png_push_save_buffer(png_ptr);
  984.          return;
  985.       }
  986.  
  987.       png_push_check_crc(png_ptr);
  988.  
  989.       key = png_ptr->current_text;
  990.       png_ptr->current_text = 0;
  991.  
  992.       for (text = key; *text; text++)
  993.          /* empty loop */ ;
  994.  
  995.       /* zTXt can't have zero text */
  996.       if (text == key + (png_size_t)png_ptr->current_text_size)
  997.       {
  998.          png_large_free(png_ptr, key);
  999.          return;
  1000.       }
  1001.  
  1002.       text++;
  1003.  
  1004.       if (*text) /* check compression byte */
  1005.       {
  1006.          png_large_free(png_ptr, key);
  1007.          return;
  1008.       }
  1009.  
  1010.       text++;
  1011.  
  1012.       png_ptr->zstream->next_in = (png_bytep )text;
  1013.       png_ptr->zstream->avail_in = (uInt)(png_ptr->current_text_size -
  1014.          (text - key));
  1015.       png_ptr->zstream->next_out = png_ptr->zbuf;
  1016.       png_ptr->zstream->avail_out = (png_size_t)png_ptr->zbuf_size;
  1017.  
  1018.       key_size = text - key;
  1019.       text_size = 0;
  1020.       text = NULL;
  1021.       ret = Z_STREAM_END;
  1022.  
  1023.       while (png_ptr->zstream->avail_in)
  1024.       {
  1025.          ret = inflate(png_ptr->zstream, Z_PARTIAL_FLUSH);
  1026.          if (ret != Z_OK && ret != Z_STREAM_END)
  1027.          {
  1028.             inflateReset(png_ptr->zstream);
  1029.             png_ptr->zstream->avail_in = 0;
  1030.             png_large_free(png_ptr, key);
  1031.             png_large_free(png_ptr, text);
  1032.             return;
  1033.          }
  1034.          if (!png_ptr->zstream->avail_out || ret == Z_STREAM_END)
  1035.          {
  1036.             if (!text)
  1037.             {
  1038.                text = (png_charp)png_large_malloc(png_ptr,
  1039.                   png_ptr->zbuf_size - png_ptr->zstream->avail_out +
  1040.                      key_size + 1);
  1041.                png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf,
  1042.                   (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
  1043.                png_memcpy(text, key, (png_size_t)key_size);
  1044.                text_size = key_size + (png_size_t)png_ptr->zbuf_size -
  1045.                   png_ptr->zstream->avail_out;
  1046.                *(text + (png_size_t)text_size) = '\0';
  1047.             }
  1048.             else
  1049.             {
  1050.                png_charp tmp;
  1051.  
  1052.                tmp = text;
  1053.                text = png_large_malloc(png_ptr, text_size +
  1054.                   png_ptr->zbuf_size - png_ptr->zstream->avail_out + 1);
  1055.                png_memcpy(text, tmp, (png_size_t)text_size);
  1056.                png_large_free(png_ptr, tmp);
  1057.                png_memcpy(text + (png_size_t)text_size, png_ptr->zbuf,
  1058.                   (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream->avail_out));
  1059.                text_size += png_ptr->zbuf_size - png_ptr->zstream->avail_out;
  1060.                *(text + (png_size_t)text_size) = '\0';
  1061.             }
  1062.             if (ret != Z_STREAM_END)
  1063.             {
  1064.                png_ptr->zstream->next_out = png_ptr->zbuf;
  1065.                png_ptr->zstream->avail_out = (uInt)png_ptr->zbuf_size;
  1066.             }
  1067.          }
  1068.          else
  1069.          {
  1070.             break;
  1071.          }
  1072.  
  1073.          if (ret == Z_STREAM_END)
  1074.             break;
  1075.       }
  1076.  
  1077.       inflateReset(png_ptr->zstream);
  1078.       png_ptr->zstream->avail_in = 0;
  1079.  
  1080.       if (ret != Z_STREAM_END)
  1081.       {
  1082.          png_large_free(png_ptr, key);
  1083.          png_large_free(png_ptr, text);
  1084.          return;
  1085.       }
  1086.  
  1087.       png_large_free(png_ptr, key);
  1088.       key = text;
  1089.       text += (png_size_t)key_size;
  1090.       text_size -= key_size;
  1091.  
  1092.       png_read_zTXt(png_ptr, info, key, text, text_size, 0);
  1093.       if (png_ptr->mode == PNG_AT_LAST_IDAT ||
  1094.          png_ptr->mode == PNG_AFTER_IDAT)
  1095.       {
  1096.          png_ptr->process_mode = PNG_READ_END_MODE;
  1097.       }
  1098.       else
  1099.       {
  1100.          png_ptr->process_mode = PNG_READ_CHUNK_MODE;
  1101.       }
  1102.    }
  1103. }
  1104. #endif
  1105.  
  1106. void
  1107. png_push_have_info(png_structp png_ptr, png_infop info)
  1108. {
  1109.    if (png_ptr->info_fn)
  1110.       (*(png_ptr->info_fn))(png_ptr, info);
  1111. }
  1112.  
  1113. void
  1114. png_push_have_end(png_structp png_ptr, png_infop info)
  1115. {
  1116.    if (png_ptr->end_fn)
  1117.       (*(png_ptr->end_fn))(png_ptr, info);
  1118. }
  1119.  
  1120. void
  1121. png_push_have_row(png_structp png_ptr, png_bytep row)
  1122. {
  1123.    if (png_ptr->row_fn)
  1124.       (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
  1125.          (int)png_ptr->pass);
  1126. }
  1127.  
  1128. png_voidp
  1129. png_get_progressive_ptr(png_structp png_ptr)
  1130. {
  1131.    return png_ptr->io_ptr;
  1132. }
  1133.  
  1134. void
  1135. png_push_read_end(png_structp png_ptr, png_infop info)
  1136. {
  1137.    if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
  1138.    {
  1139.       png_byte chunk_start[8];
  1140.  
  1141.       if (png_ptr->buffer_size < 8)
  1142.       {
  1143.          png_push_save_buffer(png_ptr);
  1144.          return;
  1145.       }
  1146.  
  1147.       png_push_fill_buffer(png_ptr, chunk_start, 8);
  1148.       png_ptr->push_length = png_get_uint_32(chunk_start);
  1149.       png_memcpy(png_ptr->push_chunk_name, (png_voidp)(chunk_start + 4), 4);
  1150.       png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
  1151.       png_reset_crc(png_ptr);
  1152.       png_calculate_crc(png_ptr, chunk_start + 4, 4);
  1153.    }
  1154.  
  1155.    if (!png_memcmp(png_ptr->push_chunk_name, png_IHDR, 4))
  1156.    {
  1157.       png_error(png_ptr, "Invalid IHDR after IDAT");
  1158.    }
  1159.    else if (!png_memcmp(png_ptr->push_chunk_name, png_PLTE, 4))
  1160.    {
  1161.       png_error(png_ptr, "Invalid PLTE after IDAT");
  1162.    }
  1163.    else if (!png_memcmp(png_ptr->push_chunk_name, png_IDAT, 4))
  1164.    {
  1165.       if (png_ptr->push_length > 0 || png_ptr->mode != PNG_AT_LAST_IDAT)
  1166.          png_error(png_ptr, "Too many IDAT's found");
  1167.    }
  1168.    else if (!png_memcmp(png_ptr->push_chunk_name, png_IEND, 4))
  1169.    {
  1170.       if (png_ptr->push_length)
  1171.          png_error(png_ptr, "Invalid IEND chunk");
  1172.       if (png_ptr->buffer_size < 4)
  1173.       {
  1174.          png_push_save_buffer(png_ptr);
  1175.          return;
  1176.       }
  1177.       png_push_check_crc(png_ptr);
  1178.       png_ptr->mode = PNG_AFTER_IEND;
  1179.       png_ptr->process_mode = PNG_READ_DONE_MODE;
  1180.       png_push_have_end(png_ptr, info);
  1181.    }
  1182. #if defined(PNG_READ_gAMA_SUPPORTED)
  1183.    else if (!png_memcmp(png_ptr->push_chunk_name, png_gAMA, 4))
  1184.    {
  1185.       png_error(png_ptr, "Invalid gAMA after IDAT");
  1186.    }
  1187. #endif
  1188. #if defined(PNG_READ_sBIT_SUPPORTED)
  1189.    else if (!png_memcmp(png_ptr->push_chunk_name, png_sBIT, 4))
  1190.    {
  1191.       png_error(png_ptr, "Invalid sBIT after IDAT");
  1192.    }
  1193. #endif
  1194. #if defined(PNG_READ_cHRM_SUPPORTED)
  1195.    else if (!png_memcmp(png_ptr->push_chunk_name, png_cHRM, 4))
  1196.    {
  1197.       png_error(png_ptr, "Invalid cHRM after IDAT");
  1198.    }
  1199. #endif
  1200. #if defined(PNG_READ_tRNS_SUPPORTED)
  1201.    else if (!png_memcmp(png_ptr->push_chunk_name, png_tRNS, 4))
  1202.    {
  1203.       png_error(png_ptr, "Invalid tRNS after IDAT");
  1204.    }
  1205. #endif
  1206. #if defined(PNG_READ_bKGD_SUPPORTED)
  1207.    else if (!png_memcmp(png_ptr->push_chunk_name, png_bKGD, 4))
  1208.    {
  1209.       png_error(png_ptr, "Invalid bKGD after IDAT");
  1210.    }
  1211. #endif
  1212. #if defined(PNG_READ_hIST_SUPPORTED)
  1213.    else if (!png_memcmp(png_ptr->push_chunk_name, png_hIST, 4))
  1214.    {
  1215.       png_error(png_ptr, "Invalid hIST after IDAT");
  1216.    }
  1217. #endif
  1218. #if defined(PNG_READ_pHYs_SUPPORTED)
  1219.    else if (!png_memcmp(png_ptr->push_chunk_name, png_pHYs, 4))
  1220.    {
  1221.       png_error(png_ptr, "Invalid pHYs after IDAT");
  1222.    }
  1223. #endif
  1224. #if defined(PNG_READ_oFFs_SUPPORTED)
  1225.    else if (!png_memcmp(png_ptr->push_chunk_name, png_oFFs, 4))
  1226.    {
  1227.       png_error(png_ptr, "Invalid oFFs after IDAT");
  1228.    }
  1229. #endif
  1230. #if defined(PNG_READ_tIME_SUPPORTED)
  1231.    else if (!png_memcmp(png_ptr->push_chunk_name, png_tIME, 4))
  1232.    {
  1233.       if (png_ptr->push_length + 4 > png_ptr->buffer_size)
  1234.       {
  1235.          png_push_save_buffer(png_ptr);
  1236.          return;
  1237.       }
  1238.  
  1239.       if (png_ptr->mode == PNG_BEFORE_IHDR ||
  1240.          png_ptr->mode == PNG_AFTER_IEND)
  1241.          png_error(png_ptr, "Out of place tIME");
  1242.  
  1243.       png_handle_tIME(png_ptr, info, png_ptr->push_length);
  1244.       png_push_check_crc(png_ptr);
  1245.    }
  1246. #endif
  1247. #if defined(PNG_READ_tEXt_SUPPORTED)
  1248.    else if (!png_memcmp(png_ptr->push_chunk_name, png_tEXt, 4))
  1249.    {
  1250.       if (png_ptr->mode == PNG_BEFORE_IHDR ||
  1251.          png_ptr->mode == PNG_AFTER_IEND)
  1252.          png_error(png_ptr, "Out of place tEXt");
  1253.  
  1254.       png_push_handle_tEXt(png_ptr, png_ptr->push_length);
  1255.    }
  1256. #endif
  1257. #if defined(PNG_READ_zTXt_SUPPORTED)
  1258.    else if (!png_memcmp(png_ptr->push_chunk_name, png_zTXt, 4))
  1259.    {
  1260.       if (png_ptr->mode == PNG_BEFORE_IHDR ||
  1261.          png_ptr->mode == PNG_AFTER_IEND)
  1262.          png_error(png_ptr, "Out of place zTXt");
  1263.  
  1264.       png_push_handle_zTXt(png_ptr, png_ptr->push_length);
  1265.    }
  1266. #endif
  1267.    else
  1268.    {
  1269.       if (png_ptr->push_chunk_name[0] <41 || png_ptr->push_chunk_name[0]> 122 ||
  1270.           (png_ptr->push_chunk_name[0]>90 && png_ptr->push_chunk_name[0]< 97) ||
  1271.           png_ptr->push_chunk_name[1] <41 || png_ptr->push_chunk_name[1]> 122 ||
  1272.           (png_ptr->push_chunk_name[1]>90 && png_ptr->push_chunk_name[1]< 97) ||
  1273.           png_ptr->push_chunk_name[2] <41 || png_ptr->push_chunk_name[2]> 122 ||
  1274.           (png_ptr->push_chunk_name[2]>90 && png_ptr->push_chunk_name[2]< 97) ||
  1275.           png_ptr->push_chunk_name[3] <41 || png_ptr->push_chunk_name[3]> 122 ||
  1276.           (png_ptr->push_chunk_name[3]>90 && png_ptr->push_chunk_name[3]< 97))
  1277.       {
  1278.          char msg[45];
  1279.  
  1280.          sprintf(msg, "Invalid chunk type 0x%02X 0x%02X 0x%02X 0x%02X",
  1281.             png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
  1282.             png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
  1283.          png_error(png_ptr, msg);
  1284.       }
  1285.  
  1286.       if ((png_ptr->push_chunk_name[0] & 0x20) == 0)
  1287.       {
  1288.          char msg[40];
  1289.  
  1290.          sprintf(msg, "Unknown critical chunk %c%c%c%c",
  1291.             png_ptr->push_chunk_name[0], png_ptr->push_chunk_name[1],
  1292.             png_ptr->push_chunk_name[2], png_ptr->push_chunk_name[3]);
  1293.          png_error(png_ptr, msg);
  1294.       }
  1295.  
  1296.       png_push_crc_skip(png_ptr, png_ptr->push_length);
  1297.    }
  1298.    if (png_ptr->mode == PNG_AT_LAST_IDAT)
  1299.       png_ptr->mode = PNG_AFTER_IDAT;
  1300.    png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
  1301. }
  1302.  
  1303. void
  1304. png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
  1305.    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
  1306.    png_progressive_end_ptr end_fn)
  1307. {
  1308.    png_ptr->info_fn = info_fn;
  1309.    png_ptr->row_fn = row_fn;
  1310.    png_ptr->end_fn = end_fn;
  1311.  
  1312.    png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
  1313. }
  1314.  
  1315. void
  1316. png_progressive_combine_row (png_structp png_ptr,
  1317.    png_bytep old_row, png_bytep new_row)
  1318. {
  1319.    if (new_row)
  1320.       png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
  1321. }
  1322.  
  1323. #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
  1324.  
  1325.